package com.guchenbo.lssp.autoconfigure;

import com.guchenbo.lssp.domain.LsspSide;
import com.guchenbo.lssp.exception.SessionException;
import com.guchenbo.lssp.pool.LivyHelper;
import com.guchenbo.lssp.pool.SessionSource;
import com.guchenbo.lssp.support.LivyProperties;
import com.guchenbo.lssp.template.LsspTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;

/**
 * @author guchenbo
 */
@Configuration
@EnableConfigurationProperties({ LsspProperties.class,
                LsspServerProperties.class })
public class LsspAutoConfiguration {
    protected static final Logger log = LoggerFactory.getLogger(LsspAutoConfiguration.class);

    private final LsspProperties lsspProperties;
    private final LsspServerProperties lsspServerProperties;

    public LsspAutoConfiguration(LsspProperties lsspProperties,
                    LsspServerProperties lsspServerProperties) {
        this.lsspProperties = lsspProperties;
        this.lsspServerProperties = lsspServerProperties;
    }

    public static final int HTTP_TIME_OUT = 5_000;

    public RestTemplate restTemplate() {
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        clientHttpRequestFactory.setConnectTimeout(HTTP_TIME_OUT);
        clientHttpRequestFactory.setConnectionRequestTimeout(HTTP_TIME_OUT);
        RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
        log.info("livy sql use normal rest template");
        restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        return restTemplate;
    }

    @Bean
    public SessionSource sessionSource() throws SessionException {
        SessionSource sessionSource = new SessionSource();
        sessionSource.setInitialSize(lsspProperties.getInitialSize());
        sessionSource.setMaxActive(lsspProperties.getMaxActive());
        sessionSource.setMinIdle(lsspProperties.getMinIdle());
        sessionSource.setShared(lsspProperties.isShared());

        sessionSource.setMaxWaitMillis(lsspProperties.getMaxWaitMillis());
        sessionSource.setTimeBetweenEvictionRunsMillis(lsspProperties.getTimeBetweenEvictionRunsMillis());

        String livyHost;
        if (LsspSide.SERVER.equals(lsspProperties.getLsspSide())) {
            livyHost = lsspServerProperties.getLivyHost();
        } else {
            livyHost = lsspProperties.getLsspServerUrl();
        }
        log.info("lssp side {} livy host {}", lsspProperties.getLsspSide(), livyHost);
        sessionSource.setLivyHost(livyHost);
        sessionSource.setSessionKind(lsspProperties.getKind());

        RestTemplate restTemplate = restTemplate();
        sessionSource.setRestTemplate(restTemplate);

        sessionSource.setLivyProperties(livyProperties());

        LivyHelper livyHelper = new LivyHelper(sessionSource.getLivyHost(), restTemplate,
                        sessionSource.getLivyProperties());

        sessionSource.setLivyHelper(livyHelper);

        if (lsspProperties.isNeedInited()) {
            sessionSource.init();
        }
        return sessionSource;
    }

    @Bean
    public LsspTemplate lsspTemplate() throws SessionException {
        return new LsspTemplate(sessionSource());
    }

    @Bean
    @ConfigurationProperties("chaos.lssp.livy")
    public LivyProperties livyProperties() {
        return new LivyProperties();
    }
}
